]> dgit.raspbian.org Git - pcre2.git/commitdiff
Backport of pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch
authorNicholas Wilson <nicholas@nicholaswilson.me.uk>
Thu, 27 Aug 2026 15:52:16 +0000 (16:52 +0100)
committerMatthew Vernon <matthew@debian.org>
Tue, 1 Sep 2026 10:43:48 +0000 (11:43 +0100)
Cherry-pick of 4889caf31a4c5a6b3c051f0031bf2dbd78f2c287

Fix invalid UTF backwards-scan reads; see GHSA-9qww-pwc4-77qq for details

(cherry picked from commit e1fd2e68fe364d14a01ec42bf07201d9820eee8e)

src/pcre2_extuni.c
src/pcre2_match.c
testdata/testinput10
testdata/testinput12
testdata/testoutput10
testdata/testoutput12-16
testdata/testoutput12-32

index 91d839e2970c4f128ab004144093f4c8d9519454..1bf1c144f1ec1835071d08dc476a36cbaec13c2c 100644 (file)
@@ -57,12 +57,12 @@ support, because some compilers do not like functionless source files. */
 
 #ifndef SUPPORT_UNICODE
 PCRE2_SPTR
-PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,
+PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR check_subject,
   PCRE2_SPTR end_subject, BOOL utf, int *xcount)
 {
 (void)c;
 (void)eptr;
-(void)start_subject;
+(void)check_subject;
 (void)end_subject;
 (void)utf;
 (void)xcount;
@@ -83,7 +83,7 @@ same behaviour.
 Arguments:
   c              the first character
   eptr           pointer to next character
-  start_subject  pointer to start of subject
+  check_subject  pointer to start of validated subject
   end_subject    pointer to end of subject
   utf            TRUE if in UTF mode
   xcount         pointer to count of additional characters,
@@ -93,7 +93,7 @@ Returns:         pointer after the end of the sequence
 */
 
 PCRE2_SPTR
-PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,
+PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR check_subject,
   PCRE2_SPTR end_subject, BOOL utf, int *xcount)
 {
 BOOL was_ep_ZWJ = FALSE;
@@ -124,7 +124,7 @@ while (eptr < end_subject)
 
     /* bptr is pointing to the left-hand character */
 
-    while (bptr > start_subject)
+    while (bptr > check_subject)
       {
       bptr--;
       if (utf)
index faedff77ce23eeef3173a9dbb581883b926c437e..7d51cf8713dc3ce92d1bb58c93b857f47a3078cc 100644 (file)
@@ -2802,7 +2802,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
     else
       {
       GETCHARINCTEST(fc, Feptr);
-      Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, utf,
+      Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject, utf,
         NULL);
       }
     CHECK_PARTIAL();
@@ -3151,7 +3151,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
           else
             {
             GETCHARINCTEST(fc, Feptr);
-            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject,
+            Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject,
               mb->end_subject, utf, NULL);
             }
           CHECK_PARTIAL();
@@ -3969,7 +3969,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
           else
             {
             GETCHARINCTEST(fc, Feptr);
-            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
+            Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject,
               utf, NULL);
             }
           CHECK_PARTIAL();
@@ -4552,7 +4552,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
           else
             {
             GETCHARINCTEST(fc, Feptr);
-            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
+            Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject,
               utf, NULL);
             }
           CHECK_PARTIAL();
@@ -6123,7 +6123,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
       {
       for (i = 0; i < Lmax; i++)
         {
-        if (Feptr == mb->start_subject)
+        if (Feptr <= mb->check_subject)
           {
           if (i < Lmin) RRETURN(MATCH_NOMATCH);
           Lmax = i;
index 3309f5e9c6936d6db6ce64b9c9ad1a4a7572f0e2..a7d30b2181bed909cf78e38b62b3979a7711be63 100644 (file)
     AAA\x80BXYZ 
     AAA\x80BBXYZ 
 
+# Backward scans must not enter the invalid prefix before check_subject.
+
+/(?<=a{1,2})X/utf,match_invalid_utf
+\= Expect no match
+    \x80X
+
+/\X\X/utf,match_invalid_utf
+\= Expect no match
+    \x80\x{1f1e6}\x{1f1e7}
+
 # -------------------------------------
 
 /(*UTF)(?=\x{123})/I
index 9763f736ef2f9e0ef0de4ff640e3f613ffd82249..b789b0038d9a0febaff050fffcbb8a762dd09e7e 100644 (file)
 /(..)(*scs:(1)ab$)/match_invalid_utf
     ab\x{df00}cde         
 
+# Backward scans must not enter the invalid prefix before check_subject.
+
+/(?<=a{1,2})X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}X
+
+/\X\X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}\x{1f1e6}\x{1f1e7}
+
 # ---------------------------------------------------- 
 
 /(*UTF)(?=\x{123})/I
index d1bccf3ef7fb28f1d3ba4bcaaa1b75f5268b1893..9b5b67011f824a7a779d94b4cdf1f0deb18cb0a5 100644 (file)
@@ -1745,6 +1745,18 @@ No match
     AAA\x80BBXYZ 
 No match
 
+# Backward scans must not enter the invalid prefix before check_subject.
+
+/(?<=a{1,2})X/utf,match_invalid_utf
+\= Expect no match
+    \x80X
+No match
+
+/\X\X/utf,match_invalid_utf
+\= Expect no match
+    \x80\x{1f1e6}\x{1f1e7}
+No match
+
 # -------------------------------------
 
 /(*UTF)(?=\x{123})/I
index bd4d524952ee341b940d7b2e862ba1037dd4b6f8..64a7dd8982dbfd40133f81045e240e1cf8cafd1e 100644 (file)
@@ -1626,6 +1626,18 @@ No match
  0: ab
  1: ab
 
+# Backward scans must not enter the invalid prefix before check_subject.
+
+/(?<=a{1,2})X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}X
+No match
+
+/\X\X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}\x{1f1e6}\x{1f1e7}
+No match
+
 # ---------------------------------------------------- 
 
 /(*UTF)(?=\x{123})/I
index c9587ee6e0df8e71cc587dba54bfc4ef273bf474..00133e29a4ceac39313c227083014ded1f8b6f85 100644 (file)
@@ -1624,6 +1624,18 @@ No match
  0: ab
  1: ab
 
+# Backward scans must not enter the invalid prefix before check_subject.
+
+/(?<=a{1,2})X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}X
+No match
+
+/\X\X/utf,match_invalid_utf
+\= Expect no match
+    \x{dc00}\x{1f1e6}\x{1f1e7}
+No match
+
 # ---------------------------------------------------- 
 
 /(*UTF)(?=\x{123})/I